<template>
    <svg width="400" height="400" class="BG" @mousemove="mousemove">
        <!-- 这样拼字符串，少些点加号，方便改一些 -->
        <path class="Line"
            :d="`M${StartPoint[0]} ${StartPoint[1]} S${ControlPoint[0]} ${ControlPoint[1]} ${EndPoint[0]} ${EndPoint[1]}`" />
        <!-- 起始点 -->
        <circle :cx="StartPoint[0]" :cy="StartPoint[1]" r="5" style="fill:pink; stroke:red; stroke-width:2;" />
        <!-- 结束点示意位置 -->
        <circle :cx="EndPoint[0]" :cy="EndPoint[1]" r="5" style="fill:pink; stroke:red; stroke-width:2;" />
        <!-- 控制点示意位置 -->
        <circle :cx="ControlPoint[0]" :cy="ControlPoint[1]" r="5" style="fill:pink; stroke:red; stroke-width:2;" />
    </svg>
</template>
<script setup>
import { nextTick, ref } from 'vue';
const StartPoint = ref([200, 200]);
const EndPoint = ref([400, 200])
const ControlPoint = ref([300, 200])

const ConstantAngle = 45;

// 未优化的计算方法
const ControlPointCompute = () => {
    // 计算起始坐标点 的 弧度值
    const radian = Math.atan2((EndPoint.value[1] - StartPoint.value[1]), (EndPoint.value[0] - StartPoint.value[0]));
    // 用 cos 弧度 来计算 偏移的角度量
    // CosRadian 弧度值为 -1 ~ 0 ~ 1 的值，可以用来进行判断坐标点左侧还是右侧
    const CosRadian = Math.cos(radian);
    // 当前两点之间的角度值
    const Angle = radian * (180 / Math.PI);
    // 控制点与原点的角度值
    const ControlAngle = Angle - (CosRadian * ConstantAngle);
    // 三角函数求 两点之间的距离（也就是斜边长）
    const distance = Math.sqrt(Math.pow(Math.abs(EndPoint.value[0] - StartPoint.value[0]), 2) + Math.pow(Math.abs(EndPoint.value[1] - StartPoint.value[1]), 2));
    // 根据弧度值，计算一个根据距离和角度决定的半径长度来计算控制点
    const distanceByCosRadian = distance / (2 - Math.abs(CosRadian) * (1 - 0.414));
    // 已知夹角，求临边长及对变长，即为二维坐标值
    const X = Math.cos(((2 * Math.PI) / 360) * ControlAngle) * distanceByCosRadian;
    const Y = Math.sin(((2 * Math.PI) / 360) * ControlAngle) * distanceByCosRadian;
    // 加上原点值，就可得出当前控制点的实际坐标值
    ControlPoint.value = [X + 200, Y + 200];
}




// 弧度值转角度值的常量
const R2A = 180 / Math.PI;
// 角度值转弧度值的常量
const A2R = (2 * Math.PI) / 360

// 优化后的计算方法(减少计算为优先)
// 优化原则：1、同样的计算不计算两次(减少计算时间)；
//          2、不创建只使用一次的变量(减少创建变量时的内存消耗)
//          3、测试完全部功能再优化(计算优化后的代码基本上是没有可读性的，所以在优化时，尽量先测试)
const TestCompute = (X, Y) => {
    // X轴坐标点差值
    const DX = Y[0] - X[0];
    // Y轴坐标点差值
    const DY = Y[1] - X[1];
    // 鼠标位置与原点的弧度值
    const radian = Math.atan2(DY, DX);
    // 鼠标点与坐标点的 余弦 值
    const CosRadian = Math.cos(radian);
    // 计算控制点与原点的距离
    const dis = Math.sqrt(Math.pow(Math.abs(DX), 2) + Math.pow(Math.abs(DY), 2)) / (2 - Math.abs(CosRadian) * (1 - 0.414));
    // 计算控制点的弧度值
    const ControlRadian = A2R * (radian * R2A - (CosRadian * ConstantAngle));
    // 计算控制点位置
    ControlPoint.value = [Math.cos(ControlRadian) * dis + X[0], Math.sin(ControlRadian) * dis + X[1]];
}

// ControlPointCompute();
TestCompute(StartPoint.value, EndPoint.value);
const mousemove = (e) => {
    // 获取当前鼠标相对父级位置
    const { offsetX, offsetY } = e;
    EndPoint.value[0] = offsetX;
    EndPoint.value[1] = offsetY;
    // ControlPointCompute();
    TestCompute(StartPoint.value, EndPoint.value);
}




</script>
<style lang="less" scoped>
.BG {
    background-color: rgba(255, 255, 255, 0.1);
}

.Line {
    fill: none;
    stroke: red;
    stroke-width: 2;
}
</style>